// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import zombie.characters.IsoSurvivor;
import zombie.characters.ZombieFootstepManager;
import zombie.characters.ZombieThumpManager;
import zombie.characters.ZombieVocalsManager;
import zombie.core.collision.Polygon;
import zombie.core.profiling.PerformanceProfileProbe;
import zombie.iso.IsoMovingObject;
import zombie.iso.IsoPushableObject;
import zombie.iso.IsoWorld;
import zombie.iso.Vector2;

public final class CollisionManager {
    static Vector2 temp = new Vector2();
    static Vector2 axis = new Vector2();
    static Polygon polygonA = new Polygon();
    static Polygon polygonB = new Polygon();
    float minA = 0.0F;
    float minB = 0.0F;
    float maxA = 0.0F;
    float maxB = 0.0F;
    zombie.CollisionManager.PolygonCollisionResult result = new zombie.CollisionManager.PolygonCollisionResult();
    public ArrayList<zombie.CollisionManager.Contact> ContactMap = new ArrayList();
    Long[] longArray = new Long[1000];
    Stack<zombie.CollisionManager.Contact> contacts = new Stack();
    public static final zombie.CollisionManager instance = new zombie.CollisionManager();

    private void ProjectPolygonA(Vector2 vector2, Polygon polygon) {
        float _float = vector2.dot((Vector2)polygon.points.get(0));
        this.minA = _float;
        this.maxA = _float;

        for (int _int = 0; _int < polygon.points.size(); _int++) {
            _float = ((Vector2)polygon.points.get(_int)).dot(vector2);
            if (_float < this.minA) {
                this.minA = _float;
            } else if (_float > this.maxA) {
                this.maxA = _float;
            }
        }
    }

    private void ProjectPolygonB(Vector2 vector2, Polygon polygon) {
        float _float = vector2.dot((Vector2)polygon.points.get(0));
        this.minB = _float;
        this.maxB = _float;

        for (int _int = 0; _int < polygon.points.size(); _int++) {
            _float = ((Vector2)polygon.points.get(_int)).dot(vector2);
            if (_float < this.minB) {
                this.minB = _float;
            } else if (_float > this.maxB) {
                this.maxB = _float;
            }
        }
    }

    public zombie.CollisionManager.PolygonCollisionResult PolygonCollision(Vector2 velocity) {
        this.result.Intersect = true;
        this.result.WillIntersect = true;
        this.result.MinimumTranslationVector.x = 0.0F;
        this.result.MinimumTranslationVector.y = 0.0F;
        int int0 = polygonA.edges.size();
        int int1 = polygonB.edges.size();
        float float0 = Float.POSITIVE_INFINITY;
        Vector2 vector20 = new Vector2();

        for (int int2 = 0; int2 < int0 + int1; int2++) {
            Vector2 vector21;
            if (int2 < int0) {
                vector21 = (Vector2)polygonA.edges.get(int2);
            } else {
                vector21 = (Vector2)polygonB.edges.get(int2 - int0);
            }

            axis.x = -vector21.y;
            axis.y = vector21.x;
            axis.normalize();
            this.minA = 0.0F;
            this.minB = 0.0F;
            this.maxA = 0.0F;
            this.maxB = 0.0F;
            this.ProjectPolygonA(axis, polygonA);
            this.ProjectPolygonB(axis, polygonB);
            if (this.IntervalDistance(this.minA, this.maxA, this.minB, this.maxB) > 0.0F) {
                this.result.Intersect = false;
            }

            float float1 = axis.dot(velocity);
            if (float1 < 0.0F) {
                this.minA += float1;
            } else {
                this.maxA += float1;
            }

            float float2 = this.IntervalDistance(this.minA, this.maxA, this.minB, this.maxB);
            if (float2 > 0.0F) {
                this.result.WillIntersect = false;
            }

            if (!this.result.Intersect && !this.result.WillIntersect) {
                break;
            }

            float2 = Math.abs(float2);
            if (float2 < float0) {
                float0 = float2;
                vector20.x = axis.x;
                vector20.y = axis.y;
                temp.x = polygonA.Center().x - polygonB.Center().x;
                temp.y = polygonA.Center().y - polygonB.Center().y;
                if (temp.dot(vector20) < 0.0F) {
                    vector20.x = -vector20.x;
                    vector20.y = -vector20.y;
                }
            }
        }

        if (this.result.WillIntersect) {
            this.result.MinimumTranslationVector.x = vector20.x * float0;
            this.result.MinimumTranslationVector.y = vector20.y * float0;
        }

        return this.result;
    }

    public float IntervalDistance(float _minA, float _maxA, float _minB, float _maxB) {
        return _minA < _minB ? _minB - _maxA : _minA - _maxB;
    }

    public void initUpdate() {
        if (this.longArray[0] == null) {
            for (int int0 = 0; int0 < this.longArray.length; int0++) {
                this.longArray[int0] = new Long(0L);
            }
        }

        for (int int1 = 0; int1 < this.ContactMap.size(); int1++) {
            ((zombie.CollisionManager.Contact)this.ContactMap.get(int1)).a = null;
            ((zombie.CollisionManager.Contact)this.ContactMap.get(int1)).b = null;
            this.contacts.push((zombie.CollisionManager.Contact)this.ContactMap.get(int1));
        }

        this.ContactMap.clear();
    }

    public void AddContact(IsoMovingObject a, IsoMovingObject b) {
        if (!(a instanceof IsoSurvivor) && !(b instanceof IsoSurvivor) || !(a instanceof IsoPushableObject) && !(b instanceof IsoPushableObject)) {
            if (a.getID() < b.getID()) {
                this.ContactMap.add(this.contact(a, b));
            }
        }
    }

    zombie.CollisionManager.Contact contact(IsoMovingObject isoMovingObject0, IsoMovingObject isoMovingObject1) {
        if (this.contacts.isEmpty()) {
            for (int _int = 0; _int < 50; _int++) {
                this.contacts.push(new zombie.CollisionManager.Contact(null, null));
            }
        }

        zombie.CollisionManager.Contact contact = (zombie.CollisionManager.Contact)this.contacts.pop();
        contact.a = isoMovingObject0;
        contact.b = isoMovingObject1;
        return contact;
    }

    public void ResolveContacts() {
        zombie.CollisionManager.s_performance.profile_ResolveContacts.invokeAndMeasure(this, zombie.CollisionManager::resolveContactsInternal);
    }

    private void resolveContactsInternal() {
        Vector2 vector20 = zombie.CollisionManager.l_ResolveContacts.vel;
        Vector2 vector21 = zombie.CollisionManager.l_ResolveContacts.vel2;
        List list = zombie.CollisionManager.l_ResolveContacts.pushables;
        ArrayList arrayList0 = IsoWorld.instance.CurrentCell.getPushableObjectList();
        int int0 = arrayList0.size();

        for (int int1 = 0; int1 < int0; int1++) {
            IsoPushableObject isoPushableObject0 = (IsoPushableObject)arrayList0.get(int1);
            if (isoPushableObject0.getImpulsex() != 0.0F || isoPushableObject0.getImpulsey() != 0.0F) {
                if (isoPushableObject0.connectList != null) {
                    list.add(isoPushableObject0);
                } else {
                    isoPushableObject0.setNx(isoPushableObject0.getNx() + isoPushableObject0.getImpulsex());
                    isoPushableObject0.setNy(isoPushableObject0.getNy() + isoPushableObject0.getImpulsey());
                    isoPushableObject0.setImpulsex(isoPushableObject0.getNx() - isoPushableObject0.getX());
                    isoPushableObject0.setImpulsey(isoPushableObject0.getNy() - isoPushableObject0.getY());
                    isoPushableObject0.setNx(isoPushableObject0.getX());
                    isoPushableObject0.setNy(isoPushableObject0.getY());
                }
            }
        }

        int int2 = list.size();

        for (int int3 = 0; int3 < int2; int3++) {
            IsoPushableObject isoPushableObject1 = (IsoPushableObject)list.get(int3);
            float float0 = 0.0F;
            float float1 = 0.0F;

            for (int int4 = 0; int4 < isoPushableObject1.connectList.size(); int4++) {
                float0 += ((IsoPushableObject)isoPushableObject1.connectList.get(int4)).getImpulsex();
                float1 += ((IsoPushableObject)isoPushableObject1.connectList.get(int4)).getImpulsey();
            }

            float0 /= (float)isoPushableObject1.connectList.size();
            float1 /= (float)isoPushableObject1.connectList.size();

            for (int int5 = 0; int5 < isoPushableObject1.connectList.size(); int5++) {
                ((IsoPushableObject)isoPushableObject1.connectList.get(int5)).setImpulsex(float0);
                ((IsoPushableObject)isoPushableObject1.connectList.get(int5)).setImpulsey(float1);
                int int6 = list.indexOf(isoPushableObject1.connectList.get(int5));
                list.remove(isoPushableObject1.connectList.get(int5));
                if (int6 <= int3) {
                    int3--;
                }
            }

            if (int3 < 0) {
                int3 = 0;
            }
        }

        list.clear();
        int int7 = this.ContactMap.size();

        for (int int8 = 0; int8 < int7; int8++) {
            zombie.CollisionManager.Contact contact = (zombie.CollisionManager.Contact)this.ContactMap.get(int8);
            if (!(Math.abs(contact.a.getZ() - contact.b.getZ()) > 0.3F)) {
                vector20.x = contact.a.getNx() - contact.a.getX();
                vector20.y = contact.a.getNy() - contact.a.getY();
                vector21.x = contact.b.getNx() - contact.b.getX();
                vector21.y = contact.b.getNy() - contact.b.getY();
                if (vector20.x != 0.0F
                    || vector20.y != 0.0F
                    || vector21.x != 0.0F
                    || vector21.y != 0.0F
                    || contact.a.getImpulsex() != 0.0F
                    || contact.a.getImpulsey() != 0.0F
                    || contact.b.getImpulsex() != 0.0F
                    || contact.b.getImpulsey() != 0.0F) {
                    float float2 = contact.a.getX() - contact.a.getWidth();
                    float float3 = contact.a.getX() + contact.a.getWidth();
                    float float4 = contact.a.getY() - contact.a.getWidth();
                    float float5 = contact.a.getY() + contact.a.getWidth();
                    float float6 = contact.b.getX() - contact.b.getWidth();
                    float float7 = contact.b.getX() + contact.b.getWidth();
                    float float8 = contact.b.getY() - contact.b.getWidth();
                    float float9 = contact.b.getY() + contact.b.getWidth();
                    polygonA.Set(float2, float4, float3, float5);
                    polygonB.Set(float6, float8, float7, float9);
                    zombie.CollisionManager.PolygonCollisionResult polygonCollisionResult = this.PolygonCollision(vector20);
                    if (polygonCollisionResult.WillIntersect) {
                        contact.a.collideWith(contact.b);
                        contact.b.collideWith(contact.a);
                        float float10 = 1.0F
                            - contact.a.getWeight(polygonCollisionResult.MinimumTranslationVector.x, polygonCollisionResult.MinimumTranslationVector.y)
                                / (
                                    contact.a.getWeight(polygonCollisionResult.MinimumTranslationVector.x, polygonCollisionResult.MinimumTranslationVector.y)
                                        + contact.b
                                            .getWeight(polygonCollisionResult.MinimumTranslationVector.x, polygonCollisionResult.MinimumTranslationVector.y)
                                );
                        if (contact.a instanceof IsoPushableObject && contact.b instanceof IsoSurvivor) {
                            ((IsoSurvivor)contact.b).bCollidedWithPushable = true;
                            ((IsoSurvivor)contact.b).collidePushable = (IsoPushableObject)contact.a;
                        } else if (contact.b instanceof IsoPushableObject && contact.a instanceof IsoSurvivor) {
                            ((IsoSurvivor)contact.a).bCollidedWithPushable = true;
                            ((IsoSurvivor)contact.a).collidePushable = (IsoPushableObject)contact.b;
                        }

                        if (contact.a instanceof IsoPushableObject) {
                            ArrayList arrayList1 = ((IsoPushableObject)contact.a).connectList;
                            if (arrayList1 != null) {
                                int int9 = arrayList1.size();

                                for (int int10 = 0; int10 < int9; int10++) {
                                    IsoPushableObject isoPushableObject2 = (IsoPushableObject)arrayList1.get(int10);
                                    isoPushableObject2.setImpulsex(
                                        isoPushableObject2.getImpulsex() + polygonCollisionResult.MinimumTranslationVector.x * float10
                                    );
                                    isoPushableObject2.setImpulsey(
                                        isoPushableObject2.getImpulsey() + polygonCollisionResult.MinimumTranslationVector.y * float10
                                    );
                                }
                            }
                        } else {
                            contact.a.setImpulsex(contact.a.getImpulsex() + polygonCollisionResult.MinimumTranslationVector.x * float10);
                            contact.a.setImpulsey(contact.a.getImpulsey() + polygonCollisionResult.MinimumTranslationVector.y * float10);
                        }

                        if (contact.b instanceof IsoPushableObject) {
                            ArrayList arrayList2 = ((IsoPushableObject)contact.b).connectList;
                            if (arrayList2 != null) {
                                int int11 = arrayList2.size();

                                for (int int12 = 0; int12 < int11; int12++) {
                                    IsoPushableObject isoPushableObject3 = (IsoPushableObject)arrayList2.get(int12);
                                    isoPushableObject3.setImpulsex(
                                        isoPushableObject3.getImpulsex() - polygonCollisionResult.MinimumTranslationVector.x * (1.0F - float10)
                                    );
                                    isoPushableObject3.setImpulsey(
                                        isoPushableObject3.getImpulsey() - polygonCollisionResult.MinimumTranslationVector.y * (1.0F - float10)
                                    );
                                }
                            }
                        } else {
                            contact.b.setImpulsex(contact.b.getImpulsex() - polygonCollisionResult.MinimumTranslationVector.x * (1.0F - float10));
                            contact.b.setImpulsey(contact.b.getImpulsey() - polygonCollisionResult.MinimumTranslationVector.y * (1.0F - float10));
                        }
                    }
                }
            }
        }

        ArrayList arrayList3 = IsoWorld.instance.CurrentCell.getObjectList();
        int int13 = arrayList3.size();
        zombie.MovingObjectUpdateScheduler.instance.postupdate();
        IsoMovingObject.treeSoundMgr.update();
        ZombieFootstepManager.instance.update();
        ZombieThumpManager.instance.update();
        ZombieVocalsManager.instance.update();
    }

    public class Contact {
        public IsoMovingObject a;
        public IsoMovingObject b;

        public Contact(IsoMovingObject isoMovingObject0, IsoMovingObject isoMovingObject1) {
            this.a = isoMovingObject0;
            this.b = isoMovingObject1;
        }
    }

    public class PolygonCollisionResult {
        public boolean WillIntersect;
        public boolean Intersect;
        public Vector2 MinimumTranslationVector = new Vector2();
    }

    private static class l_ResolveContacts {
        static final Vector2 vel = new Vector2();
        static final Vector2 vel2 = new Vector2();
        static final List<IsoPushableObject> pushables = new ArrayList();
        static IsoMovingObject[] objectListInvoking = new IsoMovingObject[1024];
    }

    private static class s_performance {
        static final PerformanceProfileProbe profile_ResolveContacts = new PerformanceProfileProbe("CollisionManager.ResolveContacts");
        static final PerformanceProfileProbe profile_MovingObjectPostUpdate = new PerformanceProfileProbe("IsoMovingObject.postupdate");
    }
}
